/**
 * Removes null, undefined, and empty string properties from an object.
 *
 * @param {Object} obj - The object to clean.
 * @returns {Object} A new object with the specified properties removed.
 *
 * @example
 * const obj = {
 *   name: 'John',
 *   age: 25,
 *   address: '',
 *   email: null,
 *   phone: undefined,
 * };
 *
 * const cleanedObj = cleanObject(obj);
 * console.log(cleanedObj); // { name: 'John', age: 25 }
 */
export function cleanObject(obj) {
	return Object.fromEntries(
		Object.entries(obj).filter(([, value]) => {
			return value !== null && value !== undefined && value !== ''
		})
	)
}

/**
 * 将树形结构扁平化
 * @param {Array} list 一个树形结构数组
 * @param {String} childrenKey 树形结构数组中子集数组的key，默认值：childNode
 * @returns {Array} 返回一个一维的数组
 */
export function flattenTree(list, childrenKey = 'childNode') {
	return list.reduce((prev, next) => {
		const { [childrenKey]: children, ...res } = next
		if (Array.isArray(children) && children.length) {
			return prev.concat(res, flattenTree(children))
		} else {
			return prev.concat(res)
		}
	}, [])
}

/**
 * 深度克隆
 * @param {*} obj 需要深度克隆的对象
 * @returns {*} 克隆后的对象或者原值（不是对象）
 */
export function deepClone(obj, cache = new WeakMap()) {
	if (obj === null || typeof obj !== 'object') return obj
	if (cache.has(obj)) return cache.get(obj)
	let clone
	if (obj instanceof Date) {
		clone = new Date(obj.getTime())
	} else if (obj instanceof RegExp) {
		clone = new RegExp(obj)
	} else if (obj instanceof Map) {
		clone = new Map(Array.from(obj, ([key, value]) => [key, deepClone(value, cache)]))
	} else if (obj instanceof Set) {
		clone = new Set(Array.from(obj, value => deepClone(value, cache)))
	} else if (Array.isArray(obj)) {
		clone = obj.map(value => deepClone(value, cache))
	} else if (Object.prototype.toString.call(obj) === '[object Object]') {
		clone = Object.create(Object.getPrototypeOf(obj))
		cache.set(obj, clone)
		for (const [key, value] of Object.entries(obj)) {
			clone[key] = deepClone(value, cache)
		}
	} else {
		clone = Object.assign({}, obj)
	}
	cache.set(obj, clone)
	return clone
}

/**
 * JS对象深度合并
 * @param {object} target 需要拷贝的对象
 * @param {object} source 拷贝的来源对象
 * @returns {object|boolean} 深度合并后的对象或者false（入参有不是对象）
 */
export function deepMerge(targetOrigin = {}, source = {}) {
	let target = deepClone(targetOrigin)
	if (typeof target !== 'object' || typeof source !== 'object') return false
	for (const prop in source) {
		if (!Object.prototype.hasOwnProperty.call(source, prop)) continue
		if (prop in target) {
			if (source[prop] == null) {
				target[prop] = source[prop]
			} else if (typeof target[prop] !== 'object') {
				target[prop] = source[prop]
			} else if (typeof source[prop] !== 'object') {
				target[prop] = source[prop]
			} else if (target[prop].concat && source[prop].concat) {
				target[prop] = target[prop].concat(source[prop])
			} else {
				target[prop] = deepMerge(target[prop], source[prop])
			}
		} else {
			target[prop] = source[prop]
		}
	}
	return target
}

/**
 * 等待一段时间
 * @param {number} ms 默认100毫秒
 * @default 100
 * @returns {Promise}
 */
export function sleep(ms = 100) {
	return new Promise(resolve => setTimeout(resolve, ms))
}
